---
title: "Filtering Memories"
description: "Filter and search memories using container tags and metadata"
icon: "filter"
---

Supermemory provides two complementary filtering mechanisms that work independently or together to help you find exactly what you need.

## How Filtering Works

Supermemory uses two types of filters for different purposes:

<CardGroup cols={2}>
  <Card title="Container Tags" icon="folder">
    **Organize memories** into isolated spaces by user, project, or workspace
  </Card>
  <Card title="Metadata Filtering" icon="database">
    **Query memories** by custom properties like category, status, or date
  </Card>
</CardGroup>

Both filtering types can be used:
- **Independently** - Use container tags alone OR metadata filters alone
- **Together** - Combine both for precise filtering (most common)

Think of it as: `[Container Tags] → [Your Memories] ← [Metadata Filters]`

## Container Tags

Container tags create isolated memory spaces. They're perfect for multi-tenant applications, user profiles, and project organization.

### How Container Tags Work

- **Exact matching**: Arrays must match exactly. A memory tagged with `["user_123", "project_ai"]` will NOT match a search for just `["user_123"]`
- **Isolation**: Each container tag combination creates a separate knowledge graph
- **Naming patterns**: Use consistent patterns like `user_{id}`, `project_{id}`, or `org_{id}_team_{id}`

### Basic Usage

<Tabs>
  <Tab title="TypeScript">
    ```typescript
    // Search within a user's memories
    const results = await client.search.documents({
      q: "machine learning notes",
      containerTags: ["user_123"],
      limit: 10
    });

    // Search within a project
    const projectResults = await client.search.documents({
      q: "requirements",
      containerTags: ["project_ai"],
      limit: 10
    });
    ```
  </Tab>
  <Tab title="Python">
    ```python
    # Search within a user's memories
    results = client.search.documents(
        q="machine learning notes",
        container_tags=["user_123"],
        limit=10
    )

    # Search within a project
    project_results = client.search.documents(
        q="requirements",
        container_tags=["project_ai"],
        limit=10
    )
    ```
  </Tab>
  <Tab title="cURL">
    ```bash
    # Search within a user's memories
    curl -X POST "https://api.supermemory.ai/v3/search" \
      -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "q": "machine learning notes",
        "containerTags": ["user_123"],
        "limit": 10
      }'
    ```
  </Tab>
</Tabs>

### Container Tag Patterns

<Tip>
**Best Practice**: Use single container tags when possible. Multi-tag arrays require exact matching, which can be restrictive.
</Tip>

#### Recommended Patterns
- User isolation: `user_{userId}`
- Project grouping: `project_{projectId}`
- Workspace separation: `workspace_{workspaceId}`
- Hierarchical: `org_{orgId}_team_{teamId}`
- Temporal: `user_{userId}_2024_q1`

#### API Differences

| Endpoint | Field Name | Type | Example |
|----------|------------|------|---------|
| `/v3/search` | `containerTags` | Array | `["user_123"]` |
| `/v4/search` | `containerTag` | String | `"user_123"` |
| `/v3/documents/list` | `containerTags` | Array | `["user_123"]` |

## Metadata Filtering

Metadata filters let you query memories by any custom property. They use SQL-like AND/OR logic with explicit grouping.

### Filter Structure

All metadata filters must be wrapped in AND or OR arrays:

```javascript
// ✅ Correct - wrapped in AND array
filters: {
  AND: [
    { key: "category", value: "tech", negate: false }
  ]
}

// ❌ Wrong - not wrapped
filters: {
  key: "category", value: "tech", negate: false
}
```

### Why Explicit Grouping?

Without explicit grouping, this SQL query is ambiguous:
```sql
category = 'tech' OR status = 'published' AND priority = 'high'
```

Our structure forces clarity:
```javascript
// Clear: (category = 'tech') OR (status = 'published' AND priority = 'high')
{
  OR: [
    { key: "category", value: "tech" },
    { AND: [
      { key: "status", value: "published" },
      { key: "priority", value: "high" }
    ]}
  ]
}
```

### Basic Metadata Filtering

<Tabs>
  <Tab title="TypeScript">
    ```typescript
    // Single condition
    const results = await client.search.documents({
      q: "neural networks",
      filters: {
        AND: [
          { key: "category", value: "ai", negate: false }
        ]
      },
      limit: 10
    });

    // Multiple AND conditions
    const filtered = await client.search.documents({
      q: "research",
      filters: {
        AND: [
          { key: "category", value: "science", negate: false },
          { key: "status", value: "published", negate: false },
          { key: "year", value: "2024", negate: false }
        ]
      },
      limit: 10
    });
    ```
  </Tab>
  <Tab title="Python">
    ```python
    # Single condition
    results = client.search.documents(
        q="neural networks",
        filters={
            "AND": [
                {"key": "category", "value": "ai", "negate": False}
            ]
        },
        limit=10
    )

    # Multiple AND conditions
    filtered = client.search.documents(
        q="research",
        filters={
            "AND": [
                {"key": "category", "value": "science", "negate": False},
                {"key": "status", "value": "published", "negate": False},
                {"key": "year", "value": "2024", "negate": False}
            ]
        },
        limit=10
    )
    ```
  </Tab>
  <Tab title="cURL">
    ```bash
    # Single condition
    curl -X POST "https://api.supermemory.ai/v3/search" \
      -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "q": "neural networks",
        "filters": {
          "AND": [
            {"key": "category", "value": "ai", "negate": false}
          ]
        },
        "limit": 10
      }'
    ```
  </Tab>
</Tabs>

## Filter Types in Detail

Supermemory supports four filter types, each designed for specific use cases.

### 1. String Equality (Default)

Exact string matching with optional case-insensitive comparison.

<Tabs>
  <Tab title="Basic">
    ```javascript
    // Case-sensitive exact match (default)
    {
      key: "status",
      value: "Published",
      negate: false
    }
    ```
  </Tab>
  <Tab title="Case-Insensitive">
    ```javascript
    // Matches "published", "Published", "PUBLISHED"
    {
      key: "status",
      value: "PUBLISHED",
      ignoreCase: true,
      negate: false
    }
    ```
  </Tab>
  <Tab title="Negation">
    ```javascript
    // Exclude specific status
    {
      key: "status",
      value: "draft",
      negate: true
    }
    ```
  </Tab>
</Tabs>

### 2. String Contains

Search for substrings within text fields.

<Tabs>
  <Tab title="Basic">
    ```javascript
    // Find all documents containing "machine learning"
    {
      filterType: "string_contains",
      key: "description",
      value: "machine learning",
      negate: false
    }
    ```
  </Tab>
  <Tab title="Case-Insensitive">
    ```javascript
    // Case-insensitive substring search
    {
      filterType: "string_contains",
      key: "title",
      value: "NEURAL",
      ignoreCase: true,
      negate: false
    }
    ```
  </Tab>
  <Tab title="Exclusion">
    ```javascript
    // Exclude documents containing "deprecated"
    {
      filterType: "string_contains",
      key: "content",
      value: "deprecated",
      negate: true
    }
    ```
  </Tab>
</Tabs>

### 3. Numeric Comparisons

Filter by numeric values with comparison operators.

<Tabs>
  <Tab title="Basic Operators">
    ```javascript
    // Greater than or equal
    {
      filterType: "numeric",
      key: "score",
      value: "80",
      numericOperator: ">=",
      negate: false
    }

    // Less than
    {
      filterType: "numeric",
      key: "readingTime",
      value: "10",
      numericOperator: "<",
      negate: false
    }
    ```
  </Tab>
  <Tab title="With Negation">
    ```javascript
    // NOT equal to 5 (becomes !=)
    {
      filterType: "numeric",
      key: "priority",
      value: "5",
      numericOperator: "=",
      negate: true
    }

    // NOT less than 80 (becomes >=)
    {
      filterType: "numeric",
      key: "score",
      value: "80",
      numericOperator: "<",
      negate: true
    }
    ```
  </Tab>
</Tabs>

<Note>
**Numeric Negation Mapping**:
When using `negate: true` with numeric filters, operators are reversed:
- `<` → `>=`
- `<=` → `>`
- `>` → `<=`
- `>=` → `<`
- `=` → `!=`
</Note>

### 4. Array Contains

Check if an array field contains a specific value.

<Tabs>
  <Tab title="Basic">
    ```javascript
    // Find documents with specific participant
    {
      filterType: "array_contains",
      key: "participants",
      value: "john.doe",
      negate: false
    }
    ```
  </Tab>
  <Tab title="Exclusion">
    ```javascript
    // Exclude documents with specific tag
    {
      filterType: "array_contains",
      key: "tags",
      value: "archived",
      negate: true
    }
    ```
  </Tab>
  <Tab title="Multiple Checks">
    ```javascript
    // Must have both participants (use AND)
    {
      AND: [
        {
          filterType: "array_contains",
          key: "participants",
          value: "project.manager"
        },
        {
          filterType: "array_contains",
          key: "participants",
          value: "lead.developer"
        }
      ]
    }
    ```
  </Tab>
</Tabs>

## Common Patterns

Ready-to-use filtering patterns for common scenarios.

### User-Specific Content with Category

<Tabs>
  <Tab title="TypeScript">
    ```typescript
    const results = await client.search.documents({
      q: "project updates",
      containerTags: ["user_123"],
      filters: {
        AND: [
          { key: "category", value: "work", negate: false },
          { key: "visibility", value: "private", negate: false }
        ]
      },
      limit: 10
    });
    ```
  </Tab>
  <Tab title="Python">
    ```python
    results = client.search.documents(
        q="project updates",
        container_tags=["user_123"],
        filters={
            "AND": [
                {"key": "category", "value": "work", "negate": False},
                {"key": "visibility", "value": "private", "negate": False}
            ]
        },
        limit=10
    )
    ```
  </Tab>
</Tabs>

### Recent High-Priority Content

<Tabs>
  <Tab title="TypeScript">
    ```typescript
    const results = await client.search.documents({
      q: "important tasks",
      filters: {
        AND: [
          {
            filterType: "numeric",
            key: "priority",
            value: "7",
            numericOperator: ">=",
            negate: false
          },
          {
            filterType: "numeric",
            key: "created_timestamp",
            value: "1704067200", // 2024-01-01
            numericOperator: ">=",
            negate: false
          }
        ]
      },
      limit: 20
    });
    ```
  </Tab>
  <Tab title="Python">
    ```python
    results = client.search.documents(
        q="important tasks",
        filters={
            "AND": [
                {
                    "filterType": "numeric",
                    "key": "priority",
                    "value": "7",
                    "numericOperator": ">=",
                    "negate": False
                },
                {
                    "filterType": "numeric",
                    "key": "created_timestamp",
                    "value": "1704067200",  # 2024-01-01
                    "numericOperator": ">=",
                    "negate": False
                }
            ]
        },
        limit=20
    )
    ```
  </Tab>
</Tabs>

### Team Collaboration Filter

<Tabs>
  <Tab title="TypeScript">
    ```typescript
    const results = await client.search.documents({
      q: "meeting notes",
      containerTags: ["project_alpha"],
      filters: {
        AND: [
          {
            OR: [
              {
                filterType: "array_contains",
                key: "participants",
                value: "alice"
              },
              {
                filterType: "array_contains",
                key: "participants",
                value: "bob"
              }
            ]
          },
          {
            key: "type",
            value: "meeting",
            negate: false
          }
        ]
      },
      limit: 15
    });
    ```
  </Tab>
  <Tab title="Python">
    ```python
    results = client.search.documents(
        q="meeting notes",
        container_tags=["project_alpha"],
        filters={
            "AND": [
                {
                    "OR": [
                        {
                            "filterType": "array_contains",
                            "key": "participants",
                            "value": "alice"
                        },
                        {
                            "filterType": "array_contains",
                            "key": "participants",
                            "value": "bob"
                        }
                    ]
                },
                {
                    "key": "type",
                    "value": "meeting",
                    "negate": False
                }
            ]
        },
        limit=15
    )
    ```
  </Tab>
</Tabs>

### Exclude Drafts and Deprecated Content

<Tabs>
  <Tab title="TypeScript">
    ```typescript
    const results = await client.search.documents({
      q: "documentation",
      filters: {
        AND: [
          {
            key: "status",
            value: "draft",
            negate: true  // Exclude drafts
          },
          {
            filterType: "string_contains",
            key: "content",
            value: "deprecated",
            negate: true  // Exclude deprecated
          },
          {
            filterType: "array_contains",
            key: "tags",
            value: "archived",
            negate: true  // Exclude archived
          }
        ]
      },
      limit: 10
    });
    ```
  </Tab>
  <Tab title="Python">
    ```python
    results = client.search.documents(
        q="documentation",
        filters={
            "AND": [
                {
                    "key": "status",
                    "value": "draft",
                    "negate": True  # Exclude drafts
                },
                {
                    "filterType": "string_contains",
                    "key": "content",
                    "value": "deprecated",
                    "negate": True  # Exclude deprecated
                },
                {
                    "filterType": "array_contains",
                    "key": "tags",
                    "value": "archived",
                    "negate": True  # Exclude archived
                }
            ]
        },
        limit=10
    )
    ```
  </Tab>
</Tabs>

## API-Specific Notes

Different endpoints have slightly different requirements:

| Endpoint | Container Tag Field | Type | Filter Format | Notes |
|----------|---------------------|------|---------------|-------|
| `/v3/search` | `containerTags` | Array | JSON object | Document search |
| `/v4/search` | `containerTag` | String | JSON object | Memory search |
| `/v3/documents/list` | `containerTags` | Array | **JSON string** | Must use `JSON.stringify()` |

<Warning>
**List API Special Requirement**: The `/v3/documents/list` endpoint requires filters as a JSON string:

```javascript
// ✅ Correct for List API
filters: JSON.stringify({ AND: [...] })

// ❌ Wrong for List API (but correct for Search API)
filters: { AND: [...] }
```
</Warning>

## Combining Container Tags and Metadata

Most real-world applications combine both filtering types for precise control.

### Example: User's Work Documents from 2024

<Tabs>
  <Tab title="TypeScript">
    ```typescript
    const results = await client.search.documents({
      q: "quarterly report",
      containerTags: ["user_123"],  // User isolation
      filters: {
        AND: [
          { key: "category", value: "work" },
          { key: "type", value: "report" },
          {
            filterType: "numeric",
            key: "year",
            value: "2024",
            numericOperator: "="
          }
        ]
      },
      limit: 10
    });
    ```
  </Tab>
  <Tab title="Python">
    ```python
    results = client.search.documents(
        q="quarterly report",
        container_tags=["user_123"],  # User isolation
        filters={
            "AND": [
                {"key": "category", "value": "work"},
                {"key": "type", "value": "report"},
                {
                    "filterType": "numeric",
                    "key": "year",
                    "value": "2024",
                    "numericOperator": "="
                }
            ]
        },
        limit=10
    )
    ```
  </Tab>
</Tabs>

### Example: Project's Active High-Priority Tasks

<Tabs>
  <Tab title="TypeScript">
    ```typescript
    const results = await client.search.documents({
      q: "implementation",
      containerTags: ["project_alpha"],  // Project isolation
      filters: {
        AND: [
          {
            key: "status",
            value: "completed",
            negate: true  // Not completed
          },
          {
            filterType: "numeric",
            key: "priority",
            value: "7",
            numericOperator: ">=",
            negate: false
          },
          {
            filterType: "array_contains",
            key: "assignees",
            value: "current_user"
          }
        ]
      },
      limit: 20
    });
    ```
  </Tab>
  <Tab title="Python">
    ```python
    results = client.search.documents(
        q="implementation",
        container_tags=["project_alpha"],  # Project isolation
        filters={
            "AND": [
                {
                    "key": "status",
                    "value": "completed",
                    "negate": True  # Not completed
                },
                {
                    "filterType": "numeric",
                    "key": "priority",
                    "value": "7",
                    "numericOperator": ">=",
                    "negate": False
                },
                {
                    "filterType": "array_contains",
                    "key": "assignees",
                    "value": "current_user"
                }
            ]
        },
        limit=20
    )
    ```
  </Tab>
</Tabs>

## Document-Specific Search

Search within a single large document using the `docId` parameter:

<Tabs>
  <Tab title="TypeScript">
    ```typescript
    // Search within a specific book or manual
    const results = await client.search.documents({
      q: "neural architecture",
      docId: "doc_textbook_ml_2024",
      limit: 20
    });
    ```
  </Tab>
  <Tab title="Python">
    ```python
    # Search within a specific book or manual
    results = client.search.documents(
        q="neural architecture",
        doc_id="doc_textbook_ml_2024",
        limit=20
    )
    ```
  </Tab>
</Tabs>

Use this for:
- Large textbooks or manuals
- Multi-chapter books
- Long podcast transcripts
- Course materials

## Validation & Limits

### Metadata Key Requirements
- **Pattern**: `/^[a-zA-Z0-9_.-]+$/`
- **Allowed**: Letters, numbers, underscore, hyphen, dot
- **Max length**: 64 characters
- **No spaces or special characters**

### Valid vs Invalid Keys
```javascript
// ✅ Valid keys
"user_email"
"created-date"
"version.number"
"priority_level_2"

// ❌ Invalid keys
"user email"        // Spaces not allowed
"created@date"      // @ not allowed
"priority!"         // ! not allowed
"very_long_key_name_that_exceeds_64_characters_limit"  // Too long
```

### Query Complexity Limits
- **Maximum conditions**: 200 per query
- **Maximum nesting depth**: 8 levels
- **Container tag arrays**: Must match exactly

## Troubleshooting

### No Results Returned

<AccordionGroup>
  <Accordion title="Container tag mismatch">
    **Problem**: Container tags must match exactly as arrays.

    **Solution**: Verify the exact array structure. `["user_123"]` ≠ `["user_123", "project_1"]`
  </Accordion>
  <Accordion title="Wrong metadata key casing">
    **Problem**: Keys are case-sensitive by default.

    **Solution**: Check exact key spelling and casing, or use `ignoreCase: true` for values.
  </Accordion>
  <Accordion title="Incorrect negate value">
    **Problem**: Using `negate: true` when you meant `false`.

    **Solution**: Review your negate values. `false` = include, `true` = exclude.
  </Accordion>
</AccordionGroup>

### Validation Errors

<AccordionGroup>
  <Accordion title="Invalid metadata key format">
    **Error**: "Invalid metadata key: contains unsafe characters"

    **Solution**: Remove spaces, special characters. Use only alphanumeric, underscore, hyphen, dot.
  </Accordion>
  <Accordion title="Filter structure error">
    **Error**: "Invalid filter structure"

    **Solution**: Ensure all conditions are wrapped in AND or OR arrays.
  </Accordion>
  <Accordion title="List API filter error">
    **Error**: "Invalid filter format"

    **Solution**: For `/v3/documents/list`, use `JSON.stringify()` on the filter object.
  </Accordion>
</AccordionGroup>

### Performance Issues

<AccordionGroup>
  <Accordion title="Slow queries">
    **Problem**: Complex nested OR conditions with many branches.

    **Solution**: Simplify logic, reduce nesting, or split into multiple queries.
  </Accordion>
  <Accordion title="Hitting complexity limits">
    **Problem**: "Query exceeds maximum complexity"

    **Solution**: Reduce conditions (max 200) or nesting depth (max 8).
  </Accordion>
</AccordionGroup>